package com.sync.platform.service.impl;

import com.sync.platform.entity.SyncTask;
import com.sync.platform.service.SyncTaskService;
import com.sync.platform.service.TaskSchedulerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * Service implementation for managing scheduled tasks
 */
@Service
public class TaskSchedulerServiceImpl implements TaskSchedulerService {
    
    private static final Logger logger = LoggerFactory.getLogger(TaskSchedulerServiceImpl.class);
    
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;
    
    @Autowired
    private SyncTaskService syncTaskService;
    
    // Map to store scheduled tasks: task ID -> ScheduledFuture
    private final Map<Long, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
    
    /**
     * Initialize scheduler by loading all active tasks on startup
     */
    @PostConstruct
    public void init() {
        logger.info("Initializing task scheduler...");
        int count = scheduleAllTasks();
        logger.info("Scheduled {} tasks from database", count);
    }
    
    @Override
    public boolean scheduleTask(Long taskId, String cronExpression) {
        if (taskId == null || cronExpression == null || cronExpression.trim().isEmpty()) {
            logger.error("Cannot schedule task: Invalid task ID or cron expression");
            return false;
        }
        
        try {
            // Cancel existing schedule if present
            cancelTask(taskId);
            
            logger.info("Scheduling task {} with cron expression: {}", taskId, cronExpression);
            
            // Create a new scheduled task
            ScheduledFuture<?> future = taskScheduler.schedule(
                () -> executeTask(taskId),
                new CronTrigger(cronExpression)
            );
            
            // Store the scheduled task
            scheduledTasks.put(taskId, future);
            
            return true;
        } catch (Exception e) {
            logger.error("Failed to schedule task {}: {}", taskId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public boolean rescheduleTask(Long taskId, String cronExpression) {
        // Same implementation as scheduleTask (cancel and reschedule)
        return scheduleTask(taskId, cronExpression);
    }
    
    @Override
    public boolean cancelTask(Long taskId) {
        ScheduledFuture<?> future = scheduledTasks.get(taskId);
        if (future != null) {
            logger.info("Cancelling scheduled task {}", taskId);
            boolean result = future.cancel(false);
            scheduledTasks.remove(taskId);
            return result;
        }
        return false;
    }
    
    @Override
    public int scheduleAllTasks() {
        List<SyncTask> tasks = syncTaskService.getDatabaseSyncTasks();
        int count = 0;
        
        for (SyncTask task : tasks) {
            // Only schedule enabled tasks with cron expressions
            if (task.getStatus() != null && task.getStatus() == 1 && 
                task.getCronExpression() != null && !task.getCronExpression().isEmpty()) {
                
                boolean scheduled = scheduleTask(task.getId(), task.getCronExpression());
                if (scheduled) {
                    count++;
                }
            }
        }
        
        return count;
    }
    
    @Override
    public List<String> getScheduledTasks() {
        List<String> taskInfo = new ArrayList<>();
        
        for (Map.Entry<Long, ScheduledFuture<?>> entry : scheduledTasks.entrySet()) {
            SyncTask task = syncTaskService.getById(entry.getKey());
            if (task != null) {
                String info = String.format("Task ID: %d, Name: %s, Cron: %s", 
                    task.getId(), task.getName(), task.getCronExpression());
                taskInfo.add(info);
            }
        }
        
        return taskInfo;
    }
    
    /**
     * Execute a sync task by its ID
     * @param taskId The ID of the task to execute
     */
    private void executeTask(Long taskId) {
        try {
            logger.info("Executing scheduled task: {}", taskId);
            Map<String, Object> result = syncTaskService.executeTask(taskId);
            boolean success = (boolean) result.get("success");
            
            if (success) {
                logger.info("Scheduled task {} executed successfully", taskId);
            } else {
                logger.error("Scheduled task {} failed: {}", taskId, result.get("message"));
            }
        } catch (Exception e) {
            logger.error("Error executing scheduled task {}: {}", taskId, e.getMessage(), e);
        }
    }
} 